Os dados

Para coletar os dados de outros países, foram utilizadas as APIs dos sites:

[1]:

import requests
import pandas as pd

covid_api = 'https://corona-api.com/countries/'
rest_countries = 'https://restcountries.eu/rest/v2/alpha/'
country = 'CN' # Alpha-2 ISO3166

data_json =  requests.get(covid_api + country).json()
country = requests.get(covid_api + country).json()

N = country['data']['population']

print(country['data']['name'])

China

Organizando os dados

[2]:

from datetime import datetime

df = pd.DataFrame(data_json['data']['timeline'])
df = df.sort_values('date').reset_index()

from datetime import datetime, timedelta
df['date'] = [datetime.fromisoformat(f) for f in df['date']]
df = df.drop_duplicates(subset='date', keep = 'last')

# Criando o vetor de tempo
first_date = df['date'].iloc[0]
size_days = (df['date'].iloc[-1] - df['date'].iloc[0]).days
date_vec = [first_date + timedelta(days=k) for k in range(size_days)]

new_df = pd.DataFrame(date_vec, columns=['date'])
new_df = pd.merge(new_df, df, how='left', on= 'date')
new_df = new_df.drop(columns= ['index',  'updated_at', 'is_in_progress'])

for col in new_df.columns[1:]:
    new_df[col] = new_df[col].interpolate(method='polynomial', order=1)
df = new_df.dropna()

df.head()

[2]:
date deaths confirmed active recovered new_confirmed new_recovered new_deaths
0 2020-01-21 17 548 503 28 548 28 17
1 2020-01-22 18 643 595 30 95 2 1
2 2020-01-23 26 920 858 36 277 6 8
3 2020-01-24 42 1406 1325 39 486 3 16
4 2020-01-25 56 2075 1970 49 669 10 14

Visualizando os dados

[3]:

from bokeh.models   import Legend, ColumnDataSource, RangeTool, LinearAxis, Range1d, HoverTool
from bokeh.palettes import brewer, Inferno256
from bokeh.plotting import figure, show
from bokeh.layouts  import column
from bokeh.io       import output_notebook

output_notebook()

import numpy as np

# Criando os valores para legenda no plot
year =  [str(int(d.year)) for d in df['date'] ]
month = [("0"+str(int(d.month)))[-2:] for d in df['date'] ]
day =   [("0"+str(int(d.day)))[-2:] for d in df['date'] ]

# Criando a fonte de dados
source = ColumnDataSource(data={
    'Data'       : df['date'].values,
    'd': day, 'm': month, 'y': year,
    'Infectados Acc' : df['confirmed'].values,
    'Mortes'     : df['deaths'].values,
    'Ativo'     : df['active'].values,
    'Recuperados': df['recovered'].values
})


# Criando a figura
p = figure(plot_height=500,
           plot_width=600,
           x_axis_type="datetime",
           tools="",
           #y_axis_type="log",
           toolbar_location=None,
           title="Evolução do COVID - " + country['data']['name'])

# Preparando o estilo
p.grid.grid_line_alpha = 0
p.ygrid.band_fill_color = "olive"
p.ygrid.band_fill_alpha = 0.1
p.yaxis.axis_label = "Indivíduos"
p.xaxis.axis_label = "Dias"

# Incluindo as curvas
i_p = p.line(x='Data', y='Ativo',
             legend_label="Infectados",
             line_cap="round", line_width=5, color="#c62828", source=source)
m_p = p.line(x='Data', y='Mortes',
             legend_label="Mortes",
             line_cap="round", line_width=5, color="#512da8", source=source)
c_p = p.line(x='Data', y='Infectados Acc',
             legend_label="Infectados Acc",
             line_cap="round", line_width=5, color="#0288d1", source=source)
r_p = p.line(x='Data', y='Recuperados',
             legend_label="Recuperados",
             line_cap="round", line_width=5, color="#388e3c", source=source)

# Colocando as legendas
p.legend.click_policy="hide"
# p.legend.location = "top_left"
p.legend.location = "top_left"

# Incluindo a ferramenta de hover
p.add_tools(HoverTool(
    tooltips=[
        ( 'Indivíduos', '$y{i}'),
        ( 'Data',       '@d/@m/@y' ),
    ],
    renderers=[
        m_p, i_p, c_p, r_p
    ]
))

show(p)

Loading BokehJS ...

Verificando os dados

[4]:

dif_I = np.diff(df['active'])
cum = []
cum.append(dif_I[0])

for k, i in enumerate(dif_I):
    cum.append(cum[-1] + i)

cum = np.array(cum)
cum += df['deaths'].to_numpy() + df['recovered'].to_numpy()

print("Erro entre casos acumulados e valores de confirmados: {}".format(
        round(sum((cum - df['confirmed'].values)**2 / len(cum)),2) ) )

Erro entre casos acumulados e valores de confirmados: 168921.0

Criando os dados SIR

[5]:

I = df['active'].to_numpy()
R = df['recovered'].to_numpy()
M = df['deaths'].to_numpy()
S = N - R - I

# Creating the time vector
t = np.linspace(0, len(I), len(I))


Sd, Id, Md, Rd, td = S, I, M, R, t

[7]:
Ro = (np.log(S[0]/N) - np.log(S[-1]/N))/(S[0]/N - S[-1]/N)
print("Calculo do Ro baseado nos dados:", Ro)
Calculo do Ro baseado nos dados: 1.0000300994523579

Estimando utilizando todos os dados

[8]:

from models import *

dataset = dict(S=Sd, I=Id, R=Rd)

# Create the model
sir_model = ss.SIR(pop=N, focus=["S", "I", "R"])

# Adjust the parameters
sir_model.fit(dataset, td,
              search_pop=True,
              pop_sens=[0.00001,0.05],
              beta_sens=[100,10000],
              r_sens=[100,100])


# Predict the model
sim_res = sir_model.predict((Sd[0],Id[0],Rd[0]), td)

Loading BokehJS ...
         ├─ S(0) ─ I(0) ─ R(0) ─  [1330043469, 503, 28]
         ├─ beta ─   1   r ─   0.14285714285714285
         ├─ beta bound ─   0.01  ─  10000
         ├─ r bound ─   0.0014285714285714286  ─  14.285714285714285
         ├─ equation weights ─   [7.51893117169047e-10, 7.90340642628301e-05, 1.8154828650455473e-05]
         ├─ Running on ─  differential_evolution SciPy Search Algorithm
         └─ Defined at:  5100.406034312756  ─  0.04454555270373974

[9]:

print("Parâmetros estimados: ", sir_model.parameters)
print("Suposto Ro: ", sir_model.parameters[0] * sir_model.parameters[-1] / sir_model.parameters[1])
print("Dias contaminados: ", 1 / sir_model.parameters[1])

Parâmetros estimados:  [5.10040603e+03 4.45455527e-02 6.14351607e-05]
Suposto Ro:  7.034243490574524
Dias contaminados:  22.448930124421754
[14]:

p = figure(plot_height=500,
           plot_width=800,
           tools="",
           toolbar_location=None,
           title="Evolução do COVID - " + country['data']['name'])

# Preparando o estilo
p.grid.grid_line_alpha = 0
p.ygrid.band_fill_color = "olive"
p.ygrid.band_fill_alpha = 0.1
p.yaxis.axis_label = "Indivíduos"
p.xaxis.axis_label = "Dias"

p.line(t, I,
       legend_label="Infectados", color="#ff6659", line_width=4)
p.line(t, R,
       legend_label="Removidos", color="#76d275", line_width=4)

# Show the results
p.line(td, sim_res[1],
       legend_label="Infectados - Modelo", line_dash="dashed", color="#d32f2f", line_width=3)
p.line(td, sim_res[2],
    legend_label="Removidos - Modelo", line_dash="dashed", color="#43a047", line_width=3)
p.line(td, sim_res[0],
      legend_label="Suscetíveis Ponderados - Modelo", line_dash="dashed", color="#1e88e5", line_width=3)
p.add_layout(p.legend[0], 'right')

show(p)

Monte Carlo

Nesta parte, faremos um teste aumentando a quantidade de amostras de treinamento e prevendo o momento do pico da epidemia a medida que mais dias são utilizados para treinamento. Esse estudo vai possibilitar a análise da certeza da previsão do pico da epidemia antes desse acontecer.

[15]:

saved_param = {'r':[], 'beta':[], 'pop':[]}
saved_prediction = []

start_day = 10
pred_t = np.array(range(int(td[-1])))

for i in range(start_day, len(I)):

    dataset = dict(S=Sd[:i], I=Id[:i], R=Rd[:i])
    td_ = td[:i]

    # Create the model
    sir_model = ss.SIR(pop=N, focus=["S", "I", "R"], verbose = False)

    # Adjust the parameters
    sir_model.fit(dataset, td_,
                  search_pop=True,
                  pop_sens=[0.00001,0.05],
                  beta_sens=[100,10000],
                  r_sens=[100,100])

    saved_param['beta'].append(sir_model.parameters[0])
    saved_param['r'].append(sir_model.parameters[1])
    saved_param['pop'].append(sir_model.parameters[2])

    saved_prediction.append(sir_model.predict((Sd[0],Id[0], Rd[0]), pred_t))
/opt/anaconda3/lib/python3.7/site-packages/scipy/integrate/odepack.py:248: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.
  warnings.warn(warning_msg, ODEintWarning)
/opt/anaconda3/lib/python3.7/site-packages/scipy/integrate/odepack.py:248: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.
  warnings.warn(warning_msg, ODEintWarning)
/opt/anaconda3/lib/python3.7/site-packages/scipy/integrate/odepack.py:248: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.
  warnings.warn(warning_msg, ODEintWarning)
/opt/anaconda3/lib/python3.7/site-packages/scipy/integrate/odepack.py:248: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.
  warnings.warn(warning_msg, ODEintWarning)
/opt/anaconda3/lib/python3.7/site-packages/scipy/integrate/odepack.py:248: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.
  warnings.warn(warning_msg, ODEintWarning)
/opt/anaconda3/lib/python3.7/site-packages/scipy/integrate/odepack.py:248: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.
  warnings.warn(warning_msg, ODEintWarning)
/opt/anaconda3/lib/python3.7/site-packages/scipy/integrate/odepack.py:248: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.
  warnings.warn(warning_msg, ODEintWarning)
/opt/anaconda3/lib/python3.7/site-packages/scipy/integrate/odepack.py:248: ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information.
  warnings.warn(warning_msg, ODEintWarning)
[17]:
import pickle

with open("./China_II_mc_runs.pickle", "wb") as handle:
    pickle.dump({"pars":saved_param, "pred":saved_prediction}, handle)

Análise do uso do sistema de saúde

Nesta análise, mostramos o erro percentual do quanto antes do pico, conseguimos prever a quantidade de pessoas que realmente serão identificadas como infectadas, uma vez que \(R(\infty)\) é a quantidade de pessoas recuperadas totais, daquelas que foram noficadas como infectadas no sistema de saúde. Desta forma segue o erro proporcional do erro a medida em que novos dados diários foram incluidos no modelo:

[34]:

x = range(start_day, len(I))
usage_error = [ 100 * abs(p*N - Rd[-1]) / Rd[-1] for p in saved_param['pop']]

fig9 = go.Figure()

fig9.add_trace(go.Scatter(
                    x=td[start_day:peak_pos],
                    y=usage_error[:peak_pos-start_day],
                    mode='lines',
                    name='Antes do pico',
                    line_shape='spline',
                    line = dict(color='royalblue', width=3),
                    hovertemplate="ε(%) = %{y:.0f}, <br> com %{x:.0f} dias de dados."))
fig9.add_trace(go.Scatter(
                    x=td[peak_pos:-1],
                    y=usage_error[peak_pos-start_day:-1],
                    mode='lines',
                    line_shape='spline',
                    name='Depois do pico',
                    line = dict(color='royalblue', width=3, dash='dot'),
                    hovertemplate="ε(%) = %{y:.0f}, <br> com %{x:.0f} dias de dados."))
fig9.add_trace(go.Scatter(
                    mode="markers", x=[peak_pos], y=[usage_error[peak_pos-start_day]],
                    marker_symbol="hexagram-dot", name="Momento do pico",
                    marker_line_color="midnightblue", marker_color="lightskyblue",
                    marker_line_width=2, marker_size=15,
                    hovertemplate="Pico no dia %{x}, com um ε(%) = %{y:.0f}."))
fig9.add_trace(go.Scatter(
                    mode="markers", x=[td[-1]], y=[usage_error[-1]],
                    marker_symbol="triangle-right-dot", name="Valor atual",
                    marker_line_color="#a00037", marker_color="#ff5c8d",
                    marker_line_width=2, marker_size=15,
                    hovertemplate="No dia %{x} da epidemia, <br> convergindo para ε(%) = %{y:.4f}."))
fig9.update_layout(template='xgridoff', yaxis_range=[-1,100],
                  legend_orientation="h", legend=dict(x=0.10, y=1.05),
                  xaxis_title='Dias (desde o começo da epidemia) utilizados para treinamento',
                  yaxis_title='Erro (%) do R(∞) - notificados',
                  title_text="Erro da previsão do uso do sistema de saúde - 🇨🇳 " + country['data']['name'])

fig9.show(renderer="png")

../_images/notebooks_SIR_Real_Data_-_COVID_-_China_Model_Analyser_19_0.png

Visualizando as previsões de \(I(t)\)

Vamos analisar as previsões quando somente os dados antes do pico são fornecidos ao modelo, e as previões utilizando os dados após o pico:

[19]:

visual_peak = 30

p2 = figure(plot_height=500,
           plot_width=600,
           tools="",
           toolbar_location=None,
           title="Evolução do COVID - " + country['data']['name'])

# Preparando o estilo
p2.grid.grid_line_alpha = 0
p2.ygrid.band_fill_color = "olive"
p2.ygrid.band_fill_alpha = 0.1
p2.yaxis.axis_label = "Indivíduos"
p2.xaxis.axis_label = "Dias"

# Incluindo as curvas
p2.line(td, Id,
       legend_label="Infectados",
       line_cap="round", line_width=3, color="#c62828")

for data in saved_prediction[visual_peak-start_day:]:
    p2.line(pred_t[:len(td)], -data[1][:len(td)],
           legend_label="Previsão Infectados - Depois do pico",
           line_cap="round", line_dash="dashed", line_width=4, color="#ffa000", line_alpha = 0.1)

for data in saved_prediction[:visual_peak-start_day]:
    p2.line(pred_t[:len(td)], -data[1][:len(td)],
           legend_label="Previsão Infectados - Antes do pico",
           line_cap="round", line_dash="dashed", line_width=4, color="#42a5f5", line_alpha = 0.3)

# Colocando as legendas
p2.legend.click_policy="hide"
p2.legend.location = "top_right"

show(p2)

Visualizando os ajustes dos grupos

Aqui vamos analisar as previsões obtidas para cada grupo \(S(t)\), \(I(t)\) e \(R(t)\), a medida que mais dias foram informados ao modelo.

[26]:

p3 = figure(plot_height=350,
           plot_width=600,
           tools="",
           toolbar_location=None,
           title="Evolução do COVID - I(t) e R(t) - " + country['data']['name'])

p4 = figure(plot_height=350,
           plot_width=600,
           tools="",
           toolbar_location=None,
           title="Evolução do COVID - S(t) - " + country['data']['name'])

plot_all = True

# Preparando o estilo
p3.grid.grid_line_alpha = 0
p3.ygrid.band_fill_color = "olive"
p3.ygrid.band_fill_alpha = 0.1
p3.yaxis.axis_label = "Indivíduos"
p3.xaxis.axis_label = "Dias"

p4.grid.grid_line_alpha = 0
p4.ygrid.band_fill_color = "olive"
p4.ygrid.band_fill_alpha = 0.1
p4.yaxis.axis_label = "Indivíduos"
p4.xaxis.axis_label = "Dias"

# Incluindo as curvas
for data in saved_prediction[20:]:
    p3.line(pred_t, data[1],
           legend_label="Previsão Infectados",
           line_cap="round", line_dash = 'dashed',
           line_width=4, color="#42a5f5", line_alpha = 0.1)

    p3.line(pred_t, data[2],
           legend_label="Previsão Recuperados",
           line_cap="round", line_dash = 'dashed', line_width=4,
           color="#9c27b0", line_alpha = 0.07)


p3.line(td, Id,
       legend_label="Infectados",
       line_cap="round", line_width=3, color="#005cb2")

p3.line(td, Rd,
           legend_label="Recuperados",
           line_cap="round", line_width=3, color="#5e35b1")

if plot_all:
    for data in saved_prediction:
        p4.line(pred_t, data[0] + N*(1-saved_param['pop'][-1]),
               legend_label="Previsão Suscetiveis",
               line_cap="round", line_dash = 'dashed',
               line_width=4, color="#ff5722", line_alpha = 0.07)
    p4.line(td, Sd,
           legend_label="Suscetiveis",
           line_cap="round", line_width=3, color="#b71c1c")

# Colocando as legendas
p3.legend.click_policy="hide"
p3.legend.location = "top_left"

p4.legend.click_policy="hide"
p4.legend.location = "top_right"

show(column(p3,p4))

Análise de variação do \(R_0\)

[33]:
x = range(start_day, len(I))
beta_norm = [b*p for b,p in zip(saved_param['beta'],saved_param['pop'])]
Ro = [b*p/r for b,r,p in zip(saved_param['beta'],saved_param['r'],saved_param['pop'])]


fig1 = go.Figure()

fig1.add_trace(go.Scatter(
                    x=td[start_day:peak_pos],
                    y=beta_norm[:peak_pos-start_day],
                    mode='lines',
                    name='Antes do pico',
                    line_shape='spline',
                    line = dict(color='royalblue', width=3),
                    hovertemplate="β = %{y:.4f}, <br> com %{x:.0f} dias de dados."))
fig1.add_trace(go.Scatter(
                    x=td[peak_pos:-1],
                    y=beta_norm[peak_pos-start_day:-1],
                    mode='lines',
                    line_shape='spline',
                    name='Depois do pico',
                    line = dict(color='royalblue', width=3, dash='dot'),
                    hovertemplate="β = %{y:.4f}, <br> com %{x:.0f} dias de dados."))
fig1.add_trace(go.Scatter(
                    mode="markers", x=[peak_pos], y=[beta_norm[peak_pos-start_day]],
                    marker_symbol="hexagram-dot", name="Momento do pico",
                    marker_line_color="midnightblue", marker_color="lightskyblue",
                    marker_line_width=2, marker_size=15,
                    hovertemplate="Pico no dia %{x}, com um β = %{y:.4f}."))
fig1.add_trace(go.Scatter(
                    mode="markers", x=[td[-1]], y=[beta_norm[-1]],
                    marker_symbol="triangle-right-dot", name="Valor atual",
                    marker_line_color="#a00037", marker_color="#ff5c8d",
                    marker_line_width=2, marker_size=15,
                    hovertemplate="No dia %{x} da epidemia, <br> convergindo para β = %{y:.4f}."))
fig1.update_layout(template='xgridoff',
                  legend_orientation="h", legend=dict(x=0.10, y=1.05),
                  xaxis_title='Dias (desde o começo da epidemia) utilizados para treinamento',
                  yaxis_title='Parâmetro β',
                  title_text="Estimativa do parâmetro β - 🇨🇳 " + country['data']['name'])

fig1.show(renderer="png")
../_images/notebooks_SIR_Real_Data_-_COVID_-_China_Model_Analyser_25_0.png
[32]:

fig2 = go.Figure()

fig2.add_trace(go.Scatter(
                    x=td[start_day:peak_pos],
                    y=saved_param['r'][:peak_pos-start_day],
                    mode='lines',
                    name='Antes do pico',
                    line_shape='spline',
                    line = dict(color='royalblue', width=3),
                    hovertemplate="r = %{y:.4f}, <br> com %{x:.0f} dias de dados."))
fig2.add_trace(go.Scatter(
                    x=td[peak_pos:-1],
                    y=saved_param['r'][peak_pos-start_day:-1],
                    mode='lines',
                    line_shape='spline',
                    name='Depois do pico',
                    line = dict(color='royalblue', width=3, dash='dot'),
                    hovertemplate="r = %{y:.4f}, <br> com %{x:.0f} dias de dados."))
fig2.add_trace(go.Scatter(
                    mode="markers", x=[peak_pos], y=[saved_param['r'][peak_pos-start_day]],
                    marker_symbol="hexagram-dot", name="Momento do pico",
                    marker_line_color="midnightblue", marker_color="lightskyblue",
                    marker_line_width=2, marker_size=15,
                    hovertemplate="Pico no dia %{x}, com um r = %{y:.4f}."))
fig2.add_trace(go.Scatter(
                    mode="markers", x=[td[-1]], y=[saved_param['r'][-1]],
                    marker_symbol="triangle-right-dot", name="Valor atual",
                    marker_line_color="#a00037", marker_color="#ff5c8d",
                    marker_line_width=2, marker_size=15,
                    hovertemplate="No dia %{x} da epidemia, <br> convergindo para r = %{y:.4f}."))
fig2.update_layout(template='xgridoff',
                  legend_orientation="h", legend=dict(x=0.07, y=1.06),
                  xaxis_title='Dias (desde o começo da epidemia) utilizados para treinamento',
                  yaxis_title='Parâmetro r',
                  title_text="Estimativa do parâmetro r - 🇨🇳 " + country['data']['name'])

fig2.show(renderer="png")

../_images/notebooks_SIR_Real_Data_-_COVID_-_China_Model_Analyser_26_0.png
[31]:

fig3 = go.Figure()

fig3.add_trace(go.Scatter(
                    x=td[start_day:peak_pos],
                    y=Ro[:peak_pos-start_day],
                    mode='lines',
                    name='Antes do pico',
                    line_shape='spline',
                    line = dict(color='royalblue', width=3),
                    hovertemplate="r = %{y:.4f}, <br> com %{x:.0f} dias de dados."))
fig3.add_trace(go.Scatter(
                    x=td[peak_pos:-1],
                    y=Ro[peak_pos-start_day:-1],
                    mode='lines',
                    line_shape='spline',
                    name='Depois do pico',
                    line = dict(color='royalblue', width=3, dash='dot'),
                    hovertemplate="Ro = %{y:.4f}, <br> com %{x:.0f} dias de dados."))
fig3.add_trace(go.Scatter(
                    mode="markers", x=[peak_pos], y=[Ro[peak_pos-start_day]],
                    marker_symbol="hexagram-dot", name="Momento do pico",
                    marker_line_color="midnightblue", marker_color="lightskyblue",
                    marker_line_width=2, marker_size=15,
                    hovertemplate="Pico no dia %{x}, com um Ro = %{y:.4f}."))
fig3.add_trace(go.Scatter(
                    mode="markers", x=[td[-1]], y=[Ro[-1]],
                    marker_symbol="triangle-right-dot", name="Valor atual",
                    marker_line_color="#a00037", marker_color="#ff5c8d",
                    marker_line_width=2, marker_size=15,
                    hovertemplate="No dia %{x} da epidemia, <br> convergindo para Ro = %{y:.4f}."))
fig3.update_layout(template='xgridoff',
                  legend_orientation="h", legend=dict(x=0.07, y=1.06),
                  xaxis_title='Dias (desde o começo da epidemia) utilizados para treinamento',
                  yaxis_title='Parâmetro Ro',
                  title_text="Estimativa do parâmetro Ro - 🇨🇳 " + country['data']['name'])

fig3.show(renderer="png")

../_images/notebooks_SIR_Real_Data_-_COVID_-_China_Model_Analyser_27_0.png

Análise de confiança

[20]:

from PyAstronomy import pyasl

dI = np.gradient(pyasl.smooth(I, 13, "hamming"))
t = np.linspace(0, len(dI), len(dI))

signal = np.array([di >= 0 for di in dI[::-1]])


import plotly.graph_objects as go

fig = go.Figure()
fig.add_trace(go.Scatter(
                    x=t[signal],
                    y=dI[::-1][signal],
                    mode='lines',
                    name='Antes do pico - Derivada positiva',
                    line_shape='spline',
                    line = dict(color='#512da8', width=3)))
fig.add_trace(go.Scatter(
                    x=t[~signal],
                    y=dI[::-1][~signal],
                    mode='lines',
                    line_shape='spline',
                    name='Depois do pico - Derivada negativa',
                    line = dict(color='#d8576b', width=3)))

fig.update_layout(template='xgridoff',
                  xaxis_title='Dias (invertido)',
                  yaxis_title='Taxa de variação de indivíduos',
                  title_text="Derivada da curva de Infectados - " + country['data']['name'])
# 'ggplot2', 'seaborn', 'simple_white', 'plotly',
# 'plotly_white', 'plotly_dark', 'presentation', 'xgridoff',
# 'ygridoff', 'gridon', 'none'

fig.show(renderer="png")

../_images/notebooks_SIR_Real_Data_-_COVID_-_China_Model_Analyser_29_0.png
[22]:

peak_pos = np.argmax(~signal[::-1])
print("O pico da epidemia acontece no dia", peak_pos)

final_day = int(td[-1])

estimated_peaks = []
for data in saved_prediction:
    dI = np.gradient(data[1][:final_day])
    signal_pred = np.array([di >= 0 for di in dI[::-1]])
    estimated_peaks.append(len(Id) - np.argmax(signal_pred))
estimated_peaks = np.array(estimated_peaks)

O pico da epidemia acontece no dia 28
[23]:

import plotly.graph_objects as go

peak_error = np.abs(estimated_peaks - peak_pos)

fig1 = go.Figure()
fig1.add_trace(go.Scatter(
                    x=td[start_day:peak_pos],
                    y=peak_error[:peak_pos-start_day],
                    mode='lines',
                    name='Antes do pico',
                    line_shape='spline',
                    line = dict(color='royalblue', width=3),
                    hovertemplate="Erro de %{y} dias, <br> com %{x:.0f} dias de dados."))
fig1.add_trace(go.Scatter(
                    x=td[peak_pos:],
                    y=peak_error[peak_pos-start_day:],
                    mode='lines',
                    line_shape='spline',
                    name='Depois do pico',
                    line = dict(color='royalblue', width=3, dash='dot'),
                    hovertemplate="Erro de %{y} dias, <br> com %{x:.0f} dias de dados."))
fig1.add_trace(go.Scatter(
                    mode="markers", x=[peak_pos], y=[peak_error[peak_pos-start_day]],
                    marker_symbol="hexagram-dot", name="Momento do pico",
                    marker_line_color="midnightblue", marker_color="lightskyblue",
                    marker_line_width=2, marker_size=15,
                    hovertemplate="Pico no dia %{x} depois do começo da epidemia."))

fig1.update_layout(yaxis_range=[-1,31],
                  template='xgridoff',
                  legend_orientation="h", legend=dict(x=0.20, y=1.0),
                  xaxis_title='Dias (desde o começo da epidemia) utilizados para treinamento',
                  yaxis_title='Erro (em dias) da estimativa do pico',
                  title_text="Erro da estimativa do pico - " + country['data']['name'])
# 'ggplot2', 'seaborn', 'simple_white', 'plotly',
# 'plotly_white', 'plotly_dark', 'presentation', 'xgridoff',
# 'ygridoff', 'gridon', 'none'

fig1.show(renderer="png")

../_images/notebooks_SIR_Real_Data_-_COVID_-_China_Model_Analyser_31_0.png